package com.laopan.elasticsearch.core.geo;

import com.laopan.elasticsearch.bean.Field;
import com.laopan.elasticsearch.bean.Page;
import com.laopan.elasticsearch.bean.geo.CenterRange;
import com.laopan.elasticsearch.bean.geo.GeoSearch;
import com.laopan.elasticsearch.bean.geo.IdGeo;
import com.laopan.elasticsearch.bean.geo.Screen;
import com.laopan.elasticsearch.core.Query;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoBoundingBoxQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 文档地理信息查询
 * @author laopan
 * @className EsGeoQuery
 * @date 2021/4/20 11:15
 */

public class GeoQuery  extends Query {
    private static final Logger log = LoggerFactory.getLogger(GeoQuery.class);

    public GeoQuery(RestHighLevelClient highLevelClient) {
        super(highLevelClient);
    }

    public SearchResponse queryById(String index, String fieldName, IdGeo idGeo) {
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.idsQuery().addIds(idGeo.getId()));
        GeoBuilder.geoSortBuilder(fieldName, idGeo.getDistancePoint(), sourceBuilder);
        return  searchRequest(request, sourceBuilder);
    }
    /**
     * 屏幕查询
     *
     * @param index
     * @param fieldName
     * @param maxSize
     * @param screen
     * @return
     */
    public SearchResponse screen(String index, String fieldName, Page page, Screen screen) {
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.geoBoundingBoxQuery(fieldName).
                setCorners(screen.getTopLeft().convertGeoPoint(), screen.getBottomRight().convertGeoPoint())
        );
        if(null!=page) {
            builder.from(page.getPageNum()).size(page.getPageSize());
        }
        GeoBuilder.geoSortBuilder(fieldName, screen.getCenter(), builder);
        return searchRequest(request, builder);
    }

    /**
     * 带查询字段的屏幕查询
     *
     * @param index
     * @param fieldName
     * @param maxSize
     * @param screen
     * @return
     */
    public SearchResponse termScreen(String index, String fieldName, Page page, Screen screen) {
        List<Field> queryFields = screen.getQueryFields();
        if (null == queryFields || queryFields.isEmpty()) {
            return screen(index, fieldName, page, screen);
        }
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        GeoBoundingBoxQueryBuilder geoBoxQuery = QueryBuilders.geoBoundingBoxQuery(fieldName).
                setCorners(screen.getTopLeft().convertGeoPoint(), screen.getBottomRight().convertGeoPoint());
        query.must(geoBoxQuery);
        queryFields.forEach(data -> query.must(QueryBuilders.termQuery(data.getName(), data.getData())));
        builder.query(query);
        if(null!=page) {
            builder.from(page.getPageNum()).size(page.getPageSize());
        }
        GeoBuilder.geoSortBuilder(fieldName, screen.getCenter(), builder);
        return searchRequest(request, builder);
    }

    /**
     * 中心点查询
     *
     * @param index
     * @param fieldName
     * @param maxSize
     * @param centerRange
     * @return
     */
    public SearchResponse centerRange(String index, String fieldName, Page page, CenterRange centerRange) {
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(centerRange.geoQueryBuilder(fieldName));
        if(null!=page) {
            builder.from(page.getPageNum()).size(page.getPageSize());
        }
        GeoBuilder.geoSortBuilder(fieldName, centerRange.getDistancePoint(), builder);
        return searchRequest(request, builder);
    }

    /**
     * 带字段的中心点查询
     *
     * @param index
     * @param fieldName
     * @param maxSize
     * @param centerRange
     * @return
     */
    public SearchResponse termCenterRange(String index, String fieldName, Page page, CenterRange centerRange) {
        List<Field> queryFields = centerRange.getQueryFields();
        if (null == queryFields || queryFields.isEmpty()) {
            return centerRange(index, fieldName, page, centerRange);
        }
        SearchRequest request = new SearchRequest(index);
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(centerRange.geoQueryBuilder(fieldName));
        queryFields.forEach(data -> query.must(QueryBuilders.termQuery(data.getName(), data.getData())));
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(query);
        if(null!=page) {
            builder.from(page.getPageNum()).size(page.getPageSize());
        }
        GeoBuilder.geoSortBuilder(fieldName, centerRange.getDistancePoint(), builder);
        return searchRequest(request, builder);
    }

    /**
     * 带字段的搜索列表
     *
     * @param index
     * @param fieldName
     * @param search
     * @return
     */
    public SearchResponse multiTermSearch(String index, String fieldName, GeoSearch search,Page page) {
        List<Field> queryFields = search.getQueryFields();
        if (null == queryFields || queryFields.isEmpty()) {
            return termSearch(index, fieldName, search,page);
        }
        String searchKey = search.getSearchKey();
        String[] fields = search.getFields();
        if (null == fields || 0 == fields.length) {
            throw new NullPointerException("查询的字段名称不为空");
        }
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if (null != searchKey && searchKey.trim().length() > 0) {
            query.must(QueryBuilders.multiMatchQuery(searchKey, fields));
        }
        queryFields.forEach(data -> query.must(QueryBuilders.termQuery(data.getName(), data.getData())));
        builder.query(query);
        if(null!=page) {
            builder.from(page.getPageNum()).size(page.getPageSize());
        }
        GeoBuilder.geoSortBuilder(fieldName, search.getPoint(), builder);
        return searchRequest(request, builder);
    }

    /**
     * 搜索列表
     *
     * @param index
     * @param fieldName
     * @param search
     * @return
     */
    public SearchResponse termSearch(String index, String fieldName, GeoSearch search,Page page) {
        String searchKey = search.getSearchKey();
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        if (null == search.getFields() || 0 == search.getFields().length) {
            throw new NullPointerException("查询的字段名称不为空");
        }
        if (null != searchKey && searchKey.trim().length() > 0) {
            builder.query(QueryBuilders.multiMatchQuery(searchKey, search.getFields()));
        }
        if(null!=page) {
            builder.from(page.getPageNum()).size(page.getPageSize());
        }
        GeoBuilder.geoSortBuilder(fieldName, search.getPoint(), builder);
        return searchRequest(request, builder);
    }

}
